import { defineNuxtPlugin } from "nuxt/app";
import * as monitor from "@zhj1214/qdjk-web";
import { useUserStore } from "~~/store/modules/user";
import { useGlobalStore } from "~~/store/global";
import { useLogStore } from "~~/store/modules/log";
import { useEventBus } from "@vueuse/core";
import { usePageVisibility } from "@vant/use";
import type { NuxtStatistics } from "~~/types/tack.ts";

/**
 * @description: 描述
 * @param {any} val
 * @return {*}
 * @author: Berry
 */
const loadMonitor = (val: any) => {
  // 网络差提示
  const showToastEmit = useEventBus("showToast-emit");
  //
  const userState = useUserStore();
  const globalStore = useGlobalStore();
  const uselog = useLogStore();
  let isUpload = true;
  // 前往登录页面的时候.取消上传错误
  const closeUploadEmit = useEventBus("qdjkWeb-closeUpload-emit");
  closeUploadEmit.on((val) => {
    isUpload = val as boolean;
  });
  // 再次进入 h5 页面的时候,恢复上传
  const pageVisibility = usePageVisibility();
  watch(pageVisibility, async (value) => {
    if (value === "visible") {
      isUpload = true;
    } else {
      isUpload = false;
    }
  });

  // 加载监控插件
  val.vueApp.use(monitor.MitoVue as any);

  monitor.init({
    apikey: "zhj1214_bdc_earlyimport_apikey", // 每个项目对应一个apikey，用于存放错误集合的唯一标识
    trackKey: "zhj1214_bdc_earlyimport_trackKey",
    debug: process.env.NODE_ENV != "development" ? true : false, // 默认不会在控制台打印用户行为和错误信息，为true时将会在控台打印，推荐本地调试时置为true
    useImgUpload: false, // 为true时，则使用img上报的方式，会在dsn后面追加data=encodeURIComponent(reportData)，在服务端接受时需要decodeURIComponent，默认为false。（小程序只能用wx.request上报的方式，也就是xhr，而且走img请求的话，url是有字符长度限制的，所以推荐走xhr）
    silentConsole: true, // 默认会监控console，为true时，将不再监控
    maxBreadcrumbs: 5, // 用户行为存放的最大容量，最大是100，当你配置超过100时，最终还是会设置成100，一方面是防止占更多的内存、一方面是保存超过100条用户行为没多大意义
    maxDuplicateCount: 2, // 注意:重复上报错误次数最小是 2
    ignoreErrors: [
      "RegExp:~RequestError~", // 请求失败
      "RegExp:~ResponseError~", // 响应失败
      "RegExp:Installations", // Firebase Installations服务链接失败: "Installations: Could not process request. Application offline. (installations/app-offline)."
      "Script error.", // 基本都是:谷歌埋点加载失败
      "Failed to execute 'observe' on 'ResizeObserver': parameter 1 is not of type 'Element'.",
      "The user aborted a request.",
      // "Cannot read properties of undefined (reading 'scrollStart')",
      "emptyMsg",
      // "Cannot read properties of undefined (reading 'scrollEnd')",
      "Write permission denied.",
      // "Cannot read properties of undefined (reading 'opts')",
      "{}",
      "RegExp:资源地址",
      "RegExp:跨域限制或域名不存在",
      "RegExp:失败原因：超时",
      "RegExp:Failed to fetch dynamically",
      "RegExp:Unable to preload",
    ], // 默认值,错误过滤
    /**
     * @description: 这里可以动态增加要过滤的信息
     * @param {any} arr 已存在的过滤信息
     * @return {*} 要过滤的信息
     */
    ignoreDynamic: async (arr: any) => {
      if (uselog.$state.ignoreDynamics.length > 0) {
        return arr.concat(uselog.$state.ignoreDynamics);
      } else {
        return arr;
      }
    },
    /**
     * @description: 埋点额外信息上报
     * @return {*} NuxtStatistics
     * @author: zhj1214
     */
    passEventTrackingInfo: async () => {
      let tackInfo: NuxtStatistics = {
        user: {
          id: `${userState.$state.sid}` || "",
          avatar: userState.$state.avatar,
          vipNum: userState.$state.vipNum,
          email: userState.$state.email,
          areaCode: userState.$state.areaCode,
          regAreaCode: userState.$state.regAreaCode,
          mobile: userState.$state.mobile,
          freeAmount: userState.$state.freeAmount,
        },
        // routes: []
      };
      return tackInfo;
    },

    // appOnShow: (data: any) => {
    //   console.log("appOnShow-data-", data);
    // },
    // appOnLaunch: (data: any) => {
    //   console.log("appOnLaunch-data-", data);
    // },
    // configReportWxRequest: (data: any) => {
    //   console.log("configReportWxRequest-data-", data);
    // },
    // beforeAppAjaxSend: (data: any) => {
    //   console.log("beforeAppAjaxSend-data-", data);
    // },
    // 这里可以给请求头增加配置
    // configReportXhr: (request: any, data: any) => {
    //   if (WEB_NODE_ENV == "dev") {
    //     console.log("configReportXhr-data-", data);
    //   }
    // },
    // 这里添加自定义上报字段数据
    beforeDataReport: async (data: any) => {
      // 1 网络差-提示信息:
      if (data.data["message"]) {
        if (
          data.data["message"].startsWith("资源地址:") &&
          data.data["type"] == "RESOURCE_ERROR" &&
          data.data["name"] == "js脚本加载失败"
        ) {
          showToastEmit.emit("common.wlycqcxjr");
          isUpload = false;
        } else if (
          data.data["message"].includes(
            "Failed to fetch dynamically imported module"
          )
        ) {
          showToastEmit.emit("common.wlycqcxjr");
          isUpload = false;
        } else if (data.data["message"].includes("Unable to preload")) {
          showToastEmit.emit("common.wlxhc");
          isUpload = false;
        }
      }

      // 1.1 是否取消上传
      if (!isUpload) return false;

      // 2. 增加上报信息
      // const { WEB_NODE_ENV = "prod" } = useRuntimeConfig().public;
      // data.deviceInfo["env"] = WEB_NODE_ENV;
      // data.deviceInfo["diviceType"] = globalStore.$state.diviceType;
      delete data.authInfo["sdkName"];
      delete data.authInfo["apikey"];
      delete data.authInfo["trackKey"];
      data.authInfo["packageId"] = globalStore.$state.packageId;
      // data.deviceInfo["packageId"] = globalStore.$state.packageId;
      // data.authInfo["email"] = userState.$state.email;
      // data.data["isLogin"] = globalStore.isLogin; // token 失效这个值是 false
      data.data["areas"] = globalStore?.$state.language; // 所使用的语言

      // 3. 如果没有登录,进入了 mining,assetDetails,exchangePoints,ranking,lottery,arousal-user 这些页面,就不需要在上传错误日志了.这样就能避免很多资源和请求取消的错误
      if (
        !globalStore.isLogin &&
        (data.data["url"].includes("/mvp/mining") ||
          data.data["url"].includes("/mvp/assetDetails") ||
          data.data["url"].includes("/mvp/exchangePoints") ||
          data.data["url"].includes("/mvp/ranking") ||
          data.data["url"].includes("/lottery") ||
          data.data["url"].includes("/arousal-user") ||
          data.data["url"].includes("/lottery-money") ||
          data.data["url"].includes("/tabbar"))
      ) {
        return false;
      }
      return data;
    },
    // trackerId表示用户唯一键（可以理解成userId），需要trackerId的意义可以区分每个错误影响的用户数量
    backTrackerId: () => {
      return userState.$state.sid || `${Date.now()}_bdc`;
    },
    // 返回数据=会导致Breadcrumb无限嵌套自己
    // beforePushBreadcrumb: (breadcrumb: any, hint: any) => {
    //   console.log("beforePushBreadcrumb-breadcrumb-", breadcrumb);
    //   console.log("beforePushBreadcrumb-hint-", hint);
    //   return breadcrumb;
    // },
    /**
     *
     * 钩子函数，每次发送前都会调用
     * @param {TransportDataType} event 上报的数据格式
     * @param {string} url 上报到服务端的地址
     * @returns {string} 返回上报的地址, 返回空时不上报
     * @memberof HooksTypes
     */
    // configReportUrl: (event:any,url:string)=>{},
    // trackDsn: "http://localhost:2021/errors/upload",
    // 错误监控上报地址，post方法，可选`useImgUpload`方式
    dsn: `${(location && location.origin) || ""}${
      process.env.NODE_ENV !== "development" ? "/fx" : ""
    }/servelog`,
    // 埋点上报地址, 将所有埋点信息上报到该服务端地址  "test-zhj1214debugger" ||
    trackDsn: `${(location && location.origin) || ""}${
      process.env.NODE_ENV !== "development" ? "/fx" : ""
    }/trackReport`,
    // trackDsn: "",
  });
};

export default defineNuxtPlugin(async (nuxtApp) => {
  // 为了更好的时候埋点，建议再写一个插件，客户端执行，单独引入sdk，并传入router 进行处理
  // nuxtApp.vueApp.use(PageAnalytics, { router: nuxtApp.$router });

  if (import.meta.client) {
    loadMonitor(nuxtApp);
  }
});
